Next: Common Lisp Compatibility, Previous: Assertions, Up: Top [Contents][Index]
Many of the advanced features of this package, such as
cl-defun, cl-loop, etc., are
implemented as Lisp macros. In byte-compiled code, these complex
notations will be expanded into equivalent Lisp code which is
simple and efficient. For example, the form
(cl-incf i n)
is expanded at compile-time to the Lisp form
(setq i (+ i n))
which is the most efficient ways of doing this operation in
Lisp. Thus, there is no performance penalty for using the more
readable cl-incf form in your compiled code.
Interpreted code, on the other hand, must expand
these macros every time they are executed. For this reason it is
strongly recommended that code making heavy use of macros be
compiled. A loop using cl-incf a hundred times will
execute considerably faster if compiled, and will also
garbage-collect less because the macro expansion will not have to
be generated, used, and thrown away a hundred times.
You can find out how a macro expands by using the
cl-prettyexpand function.
This function takes a single Lisp form as an argument and inserts a nicely formatted copy of it in the current buffer (which must be in Lisp mode so that indentation works properly). It also expands all Lisp macros that appear in the form. The easiest way to use this function is to go to the *scratch* buffer and type, say,
(cl-prettyexpand '(cl-loop for x below 10 collect x))
and type C-x C-e immediately after the closing parenthesis; an expansion similar to:
(cl-block nil
(let* ((x 0)
(G1004 nil))
(while (< x 10)
(setq G1004 (cons x G1004))
(setq x (+ x 1)))
(nreverse G1004)))
will be inserted into the buffer. (The
cl-block macro is expanded differently in the
interpreter and compiler, so cl-prettyexpand
just leaves it alone. The temporary variable
G1004 was created by
cl-gensym.)
If the optional argument full is true, then
all macros are expanded, including
cl-block, cl-eval-when, and
compiler macros. Expansion is done as if form were
a top-level form in a file being compiled.
Note that cl-adjoin, cl-caddr,
and cl-member all have built-in compiler macros
to optimize them in common cases.
Common Lisp compliance has in general not been sacrificed for the sake of efficiency. A few exceptions have been made for cases where substantial gains were possible at the expense of marginal incompatibility.
The Common Lisp standard (as embodied in Steele’s book)
uses the phrase “it is an error if” to indicate a
situation that is not supposed to arise in complying programs;
implementations are strongly encouraged but not required to
signal an error in these situations. This package sometimes omits
such error checking in the interest of compactness and
efficiency. For example, cl-do variable specifiers
are supposed to be lists of one, two, or three forms; extra forms
are ignored by this package rather than signaling a syntax error.
Functions taking keyword arguments will accept an odd number of
arguments, treating the trailing keyword as if it were followed
by the value nil.
Argument lists (as processed by cl-defun and
friends) are checked rigorously except for the minor
point just mentioned; in particular, keyword arguments are
checked for validity, and &allow-other-keys and
:allow-other-keys are fully implemented. Keyword
validity checking is slightly time consuming (though not too bad
in byte-compiled code); you can use
&allow-other-keys to omit this check. Functions
defined in this package such as cl-find and
cl-member do check their keyword arguments for
validity.
Changing the value of byte-optimize from the
default t is highly discouraged; many of the Common
Lisp macros emit code that can be improved by optimization. In
particular, cl-blocks (whether explicit or implicit
in constructs like cl-defun and
cl-loop) carry a fair run-time penalty; the
byte-compiler removes cl-blocks that are not
actually referenced by cl-return or
cl-return-from inside the block.
Next: Common Lisp Compatibility, Previous: Assertions, Up: Top [Contents][Index]